<!DOCTYPE html>
<script src='../../resources/testharness.js'></script>
<script src='../../resources/testharnessreport.js'></script>
<script src='../../resources/gesture-util.js'></script>

<style>
  body, html {
    margin: 0;
  }
  div {
    line-height: 50px;
  }

  .hoverme {
    background-color: lightblue;
  }
</style>

<table id="table_to_fill" width="100%" cellpadding="0px" cellspacing="0px" border="0px">
</table>

<script>
  
  let array;
  const numHoverElements = 30;
  const elementHeight = 50;
  const textWhenNotHovered = "hover over me";
  const textWhenHovered = "currently hovered";
  const textWhenWasHovered = "was hovered";
  const mouse = GestureSourceType.MOUSE_INPUT;

  function centerOfDivAtIndex(n) {
    return elementHeight * n + elementHeight / 2;
  }


  function buildPage() {
    let table = document.getElementById('table_to_fill');
    for (let i = 0; i < numHoverElements; i++) {
      let p = document.createElement('tr');
      p.innerHTML = '<tr><td><div class="hoverme">' + textWhenNotHovered + '</div></td></tr>';
      table.appendChild(p);
    }

    array = document.getElementsByClassName('hoverme');

    for (let i = 0; i < array.length; i++) {
      array[i].addEventListener('mouseover', function (e) {
        this.innerHTML = textWhenHovered;
        this.style.backgroundColor = "yellow";
      });
      array[i].addEventListener('mouseout', function (e) {
        this.innerHTML = textWhenWasHovered;
        this.style.backgroundColor = "green";
      });
    }
  }

  window.onload = async () => {
    if (window.internals)
      internals.settings.setScrollAnimatorEnabled(false);

    buildPage();
    await waitForCompositorCommit();

    promise_test(async () => {
      let x = 50;
      let y = centerOfDivAtIndex(0);
      // Move cursor to 1st element.
      await mouseMoveTo(x, y);
      await waitFor( () => { return array[0].innerHTML == textWhenHovered;}, 'wait for move to 1st element');
      assert_equals(array[0].innerHTML, textWhenHovered);
      assert_equals(array[1].innerHTML, textWhenNotHovered);

      // Move cursor to 2nd element.
      y = centerOfDivAtIndex(1);
      await mouseMoveTo(x, y);
      await waitFor( () => { return array[1].innerHTML == textWhenHovered;}, 'wait for move to 2nd element');
      assert_equals(array[0].innerHTML, textWhenWasHovered);
      assert_equals(array[1].innerHTML, textWhenHovered);
      assert_equals(array[2].innerHTML, textWhenNotHovered);

      // Scroll end up at 4th element. Hover state does not update during scrolling
      // so that 3rd element keeps not hover state.
      assert_equals(document.scrollingElement.scrollTop, 0);
      await smoothScroll(2 * elementHeight, x, y, mouse, 'down', SPEED_INSTANT);
      await waitFor( () => { return array[3].innerHTML == textWhenHovered;}, 'wait for scroll stop at 4th element');
      assert_equals(array[0].innerHTML, textWhenWasHovered);
      assert_equals(array[1].innerHTML, textWhenWasHovered);
      assert_equals(array[2].innerHTML, textWhenNotHovered);
      assert_equals(array[3].innerHTML, textWhenHovered);
      assert_equals(array[4].innerHTML, textWhenNotHovered);
      assert_approx_equals(document.scrollingElement.scrollTop, 2 * elementHeight, 2);

      // Hide cursor and scroll end up at 5th element. No hover state should update.
      internals.setIsCursorVisible(document, false);
      await smoothScroll(elementHeight, x, y, mouse, 'down', SPEED_INSTANT, true /* precise_scrolling_deltas */, false /* scroll_by_page */, false /* cursor_visible */);
      await waitFor( () => {
        return document.scrollingElement.scrollTop >= 3 * elementHeight - 10 && document.scrollingElement.scrollTop <= 3 * elementHeight + 10;}, 'wait for scroll stop at 5th element');
      // Wait enough time to see if we fire a fake mouse move event to update the hover state.
      await waitForAnimationEnd(() => { return document.scrollingElement.scrollTop; }, 200, 60);
      assert_equals(array[0].innerHTML, textWhenWasHovered);
      assert_equals(array[1].innerHTML, textWhenWasHovered);
      assert_equals(array[2].innerHTML, textWhenNotHovered);
      assert_equals(array[3].innerHTML, textWhenHovered);
      assert_equals(array[4].innerHTML, textWhenNotHovered);
      assert_equals(array[5].innerHTML, textWhenNotHovered);

    }, 'crbug.com/153784 New hover effects should not be invoked during scroll if the mouse cursor is not visible.');
  }

</script>